package com.om.abom.utils;

import com.alibaba.fastjson2.JSON;
import com.om.abom.entity.AppServerEntity;
import com.om.abom.service.AppServerService;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
@Getter
public class PsInfoSender
{
    public static final String CMD_GET_PS_INFO = "ps -eo pid,lstart,etime,rss,pcpu,cmd |grep -v grep |grep abom";

    private final HashMap<String, PsInfo> allHostPsInfo = new HashMap<>();

    @Autowired
    AppServerService appServerService;

    // 发送所有主机的 abom 进程信息
    public void sendAllHostPsInfo(WebSocketSession socketSession)
    {
        List<AppServerEntity> appServers = appServerService.list();

        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

        Runnable sendPsInfo = () -> {
            for (AppServerEntity appServer : appServers) {
                putPsInfo(appServer.getHostIp());
            }
            try {
                String jsonString = JSON.toJSONString(allHostPsInfo);
                log.debug(jsonString);
                // 好像是不能多个线程同时用一个 socketSession 发送消息
                socketSession.sendMessage(new TextMessage(jsonString));
            } catch (IOException e) {
                log.error("scheduler shutdown! ", e);
                scheduler.shutdown();
            }
        };
        scheduler.scheduleAtFixedRate(sendPsInfo, 2, 3, TimeUnit.SECONDS);
    }

    public void putPsInfo(String ip)
    {
        JschExecutor jschExecutor = null;
        log.debug("putPsInfo start, {} ", ip);
        try {
            jschExecutor = new JschExecutor(ip);
            String psInfoStr = jschExecutor.execCmd(CMD_GET_PS_INFO);
            log.debug("putPsInfo: {}, {}", ip, psInfoStr);
            allHostPsInfo.put(ip, formatPsInfo(psInfoStr));
        } catch (Exception e) {
            log.debug("putPsInfo exception {}", ip, e);
            if (jschExecutor != null) {
                jschExecutor.disconnect();
            }
        }
        log.debug("putPsInfo end, {}", ip);
    }

    public static PsInfo formatPsInfo(String psInfoStr)
    {
        // System.out.println(psInfoStr);
        // 26001 Mon Mar 11 07:19:38 2024    07:19:03 142452 0.1 java -jar /root/abom-0.0.1-SNAPSHOT.jar
        // 26001 Mon Mar 11 07:19:38 2024 07:19:03 142452 0.1 java -jar /root/abom-0.0.1-SNAPSHOT.jar
        // 复制出的字符串只有一个空格，而实际是个tab，导致测试时没问题，实际使用时前端页面显示的是 {}
        Pattern pattern = Pattern.compile("^\\s*(\\d+)\\s+(.*?\\s\\d{2}:\\d{2}:\\d{2}\\s+\\d{4})\\s+([\\d:]+)\\s+(\\d+)\\s([\\d.]+)");
        Matcher matcher = pattern.matcher(psInfoStr);

        PsInfo psInfo = null;
        if (matcher.find()) {
            String rss = FileUtils.byteCountToDisplaySize(Long.parseLong(matcher.group(4)) * 1024);
            psInfo = new PsInfo(matcher.group(1), matcher.group(2), matcher.group(3), rss, matcher.group(5));
        }
        return psInfo;
    }

    public record PsInfo(
            String processId,
            String latestStartTime,
            String elapsedTime,
            String residentSetSize,
            String percentCpu
    )
    {
    }
}
